Axir Verifying Paymaster
The Axir Verifying Paymaster is an ERC-4337 compliant Paymaster contract that uses an external service to decide whether to pay for a UserOperation. It trusts an external signer to validate and sign transactions before they are submitted on-chain.
Overview
This paymaster relies on an off-chain service to perform validations and sign UserOperations. The user must first submit their UserOperation to this external service, which then signs it if it passes the off-chain verification process. This signature is then included in the paymasterAndData
field of the UserOperation.
Key features:
- Off-chain validation and signing
- On-chain signature verification
- Configurable validity period for UserOperations
- Gas balance tracking and deduction
Contract Details
- License: GPL-3.0
- js Version: 0.8.23
- Base Contract: BasePaymaster
Constructor
constructor(
IEntryPoint _entryPoint,
address _verifyingSigner
) payable BasePaymaster(_entryPoint)
Initializes the Axir Verifying Paymaster contract with the following parameters:
_entryPoint
: The ERC-4337 EntryPoint contract_verifyingSigner
: The address of the trusted external signer
Key Functions
getHash
function getHash(
PackedUserOperation calldata userOp,
uint48 validUntil,
uint48 validAfter
) public view returns (bytes32)
Calculates the hash of the UserOperation that will be signed off-chain and validated on-chain. This hash includes all fields of the UserOperation except for paymasterAndData
.
_validatePaymasterUserOp
function _validatePaymasterUserOp(
PackedUserOperation calldata userOp,
bytes32 userOpHash,
uint256 requiredPreFund
) public view override returns (bytes memory context, uint256 validationData)
Verifies that the external signer has signed the UserOperation. It checks the signature included in the paymasterAndData
field.
parsePaymasterAndData
function parsePaymasterAndData(
bytes calldata paymasterAndData
) public pure returns (uint48 validUntil, uint48 validAfter, bytes calldata signature)
Parses the paymasterAndData
field to extract the validity period and signature.
_postOp
function _postOp(
PostOpMode mode,
bytes calldata context,
uint256 actualGasCost,
uint256 actualUserOpFeePerGas
) internal virtual override
Executes the paymaster's payment conditions after the UserOperation has been processed. It deducts the gas cost from the paymaster's balance.
Events
GasBalanceDeducted
event GasBalanceDeducted(
address indexed _paymaster,
uint256 indexed _amount
)
Emitted when gas balance is deducted from the paymaster.
Paymaster Data Structure
The paymasterAndData
field in the UserOperation should be structured as follows:
[:20]
: address of this paymaster[20:84]
: abi.encode(validUntil, validAfter)[84:]
: signature
Security Considerations
- The contract relies on the integrity of the external signer. Compromise of the signer's private key could lead to unauthorized UserOperations being approved.
- The validity period (validUntil, validAfter) should be carefully set to prevent replay attacks.
- The contract does not implement a deposit system, so the contract owner must ensure sufficient balance for gas payments.
Usage
- User creates a UserOperation
- User sends the UserOperation to the off-chain service
- Off-chain service validates the UserOperation and signs it
- User includes the signature and validity period in the
paymasterAndData
field - User submits the UserOperation to the EntryPoint
- EntryPoint calls the paymaster to validate the UserOperation
- Paymaster verifies the signature and validity period
- If valid, the UserOperation is executed, and the paymaster pays for the gas
This paymaster design separates the concerns of account validation (done by the account itself) and payment authorization (done by the paymaster). The off-chain service can implement complex logic and integrations to decide whether to sponsor a transaction.